package main

import (
	"encoding/json"
	"fmt"
	"github.com/go-redis/redis"
	"github.com/gorilla/websocket"
	"github.com/jageros/eventhub"
	"log"
	"net/http"
	"znzc_websocket/configs"
	"znzc_websocket/dao"
	"znzc_websocket/domain"
	"znzc_websocket/web"
)

func main() {

	//加载配置信息
	viper()

	client := dao.OpenRedis()

	DB, _ := dao.OpenDataBases()

	websocketPort := configs.GetWebsocketPort()

	//先拿到监控主机的监控信息，然后再进行数据推送

	go func(client *redis.Client) {
		//订阅redis频道的监控数据信息
		dao.Subscribe(client)
	}(client)

	//处理websocket请求信息
	http.HandleFunc("/ws", func(writer http.ResponseWriter, request *http.Request) {

		wsConn := web.WsHandler(writer, request)
		// 处理器
		go wsConn.ProcLoop()
		// 读协程
		go wsConn.WsReadLoop()
		// 写协程
		go wsConn.WsWriteLoop()

		//查询数据库当前数据库的主机个数
		servers := dao.SelectInfo(DB)

		//等待收到的数据个数和数据库的个数一样
		hostNum := len(servers)

		monitor := new(domain.Monitor)
		subscribes := make([]domain.Subscribe, hostNum)

		monitor.Result = "200"
		monitor.Data = subscribes

		increase := 0

		var ipUnique map[string]int /*创建集合 */
		ipUnique = make(map[string]int)

		fmt.Println(ipUnique)
		log.Println("推送条件map：", ipUnique)

		// 监听事件
		eventhub.Subscribe(1, func(args ...interface{}) {

			if !wsConn.IsClosed {

				//msg, err := wsConn.wsRead()
				//
				//if err != nil {
				//	log.Println("接收前端传过来的数据失败！")
				//	fmt.Println("read fail")
				//}
				//
				//log.Println("前端传过来的数据：", string(msg.data))

				//fmt.Println("监听器中读取前端传过来的数据，数据为:", *recMsg)

				//	log.Printf("Subscribe1 eventId=1 args=%v\n", args)

				if val, ok := args[0].(string); ok {

					if increase != hostNum && len(ipUnique) != hostNum {

						subscribe := domain.Subscribe{}

						_ = json.Unmarshal([]byte(val), &subscribe)

						subscribes[increase] = subscribe

						ipUnique[subscribe.CollectorIp] = increase

						increase = increase + 1

					} else {

						b, err := json.Marshal(monitor)

						if err != nil {

							log.Println("监控信息序列化失败：失败信息为：", err)
							monitor.Result = "300"
							monitor.Data = []domain.Subscribe{}

							//发送错误数据信息
							err = wsConn.WsWrite(websocket.TextMessage, b)
							if err != nil {
								log.Println("write fail")
							}

							retry(monitor, subscribes, hostNum, &increase)
							ipUnique = make(map[string]int)

						} else {

							//发送监控数据信息
							err = wsConn.WsWrite(websocket.TextMessage, b)
							if err != nil {
								log.Println("write fail")
							}

							retry(monitor, subscribes, hostNum, &increase)
							ipUnique = make(map[string]int)

						}

					}

				}
			}

		})

		//// 这是一个同步处理模型（只是一个例子），如果希望并行处理可以每个请求一个gorutine，注意控制并发goroutine的数量!!!
		//for {
		//	msg, err := wsConn.wsRead()
		//	if err != nil {
		//		fmt.Println("read fail")
		//		break
		//	}
		//	fmt.Println(string(msg.data))
		//	err = wsConn.wsWrite(msg.messageType, msg.data)
		//	if err != nil {
		//		fmt.Println("write fail")
		//		break
		//	}
		//}

	})

	_ = http.ListenAndServe(websocketPort, nil)

}

func retry(monitor *domain.Monitor, subscribes []domain.Subscribe, hostNum int, increase *int) {

	//数据推送完成，清空切片数据
	subscribes = subscribes[0:0]

	monitor = new(domain.Monitor)
	subscribes = make([]domain.Subscribe, hostNum)

	monitor.Result = "200"
	monitor.Data = subscribes
	*increase = 0

}

func viper() {
	//vipConfig是配置
	vipConfig, err := configs.Init()
	log.Println("config.init error是:", err)
	log.Println("config.init vipConfig是:", vipConfig)
}
